

package com.maoshi.shop.service.impl;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.maoshi.shop.bean.app.param.PayParam;
import com.maoshi.shop.bean.enums.OrderType;
import com.maoshi.shop.common.enums.PayType;
import com.maoshi.shop.bean.enums.ScoreLogType;
import com.maoshi.shop.bean.event.PaySuccessOrderEvent;
import com.maoshi.shop.bean.event.UpdateUserScoreEvent;
import com.maoshi.shop.bean.model.Order;
import com.maoshi.shop.bean.model.OrderItem;
import com.maoshi.shop.bean.model.OrderSettlement;
import com.maoshi.shop.bean.pay.PayInfoDto;
import com.maoshi.shop.common.exception.MaoshiShopBindException;
import com.maoshi.shop.common.util.Arith;
import com.maoshi.shop.dao.OrderMapper;
import com.maoshi.shop.dao.OrderSettlementMapper;
import com.maoshi.shop.service.PayService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author lgh on 2018/09/15.
 */
@Slf4j
@Service
@AllArgsConstructor
public class PayServiceImpl implements PayService {

    private final OrderMapper orderMapper;
    private final OrderSettlementMapper orderSettlementMapper;
    private final ApplicationEventPublisher eventPublisher;
    private final Snowflake snowflake;

    /**
     * 不同的订单号，同一个支付流水号
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public PayInfoDto pay(String userId, PayParam payParam) {
        // 支付单号
        String payNo = String.valueOf(snowflake.nextId());
        String[] orderNumbers = payParam.getOrderNumbers().split(StrUtil.COMMA);
        // 应支付的总金额
        double payAmount = 0.0;
        int isScore = 0;
        // 修改订单信息
        for (String orderNumber : orderNumbers) {
            OrderSettlement orderSettlement = orderSettlementMapper.selectOne(
                    new LambdaQueryWrapper<OrderSettlement>()
                            .eq(OrderSettlement::getUserId,userId)
                            .eq(OrderSettlement::getOrderNumber,orderNumber)
            );
            if (Objects.equals(orderSettlement.getPayStatus(), 1)) {
                throw new MaoshiShopBindException("支付失败，订单不在未支付状态");
            }
            Order order = orderMapper.getOrderByOrderNumber(orderNumber);
            order.setPayType(payParam.getPayType());
            orderMapper.updateById(order);

            //如果金额为0的积分订单更新用户积分和添加日志,并走一遍流程
            orderSettlement.setPayNo(payNo);
            orderSettlement.setPayType(payParam.getPayType());
            orderSettlement.setUserId(userId);
            orderSettlement.setOrderNumber(orderNumber);
            if(Objects.equals(order.getOrderType(),OrderType.SCORE.value()) && orderSettlement.getPayScore() > 0 &&orderSettlement.getPayAmount() < 0.01) {
                isScore = 1;
                orderSettlement.setPayAmount(0.0);
                orderSettlementMapper.updateByOrderNumberAndUserId(orderSettlement);
                paySuccess(payNo, null);
                break;
            }
            payAmount = Arith.add(payAmount, orderSettlement.getPayAmount());
            orderSettlementMapper.updateByOrderNumberAndUserId(orderSettlement);
        }

        PayInfoDto payInfoDto = new PayInfoDto();
        payInfoDto.setBody("商城订单");
        payInfoDto.setPayAmount(payAmount);
        payInfoDto.setPayNo(payNo);
        payInfoDto.setIsScore(isScore);
        return payInfoDto;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<Order> paySuccess(String payNo, String bizPayNo) {
        List<OrderSettlement> orderSettlements = orderSettlementMapper.selectList(new LambdaQueryWrapper<OrderSettlement>().eq(OrderSettlement::getPayNo, payNo));
        OrderSettlement settlement = orderSettlements.get(0);
        List<String> orderNumbers = orderSettlements.stream().map(OrderSettlement::getOrderNumber).collect(Collectors.toList());
        // 订单已支付
        if (settlement.getPayStatus() == 1) {
            log.info("订单已支付，settlement.id：{}", settlement.getSettlementId());
            return Collections.emptyList();
        }
        // 修改订单结算信息
        if (orderSettlementMapper.updateToPay(payNo, settlement.getVersion()) < 1) {
            throw new MaoshiShopBindException("结算信息已更改");
        }
        // 将订单改为已支付状态
        orderMapper.updateByToPaySuccess(orderNumbers, PayType.WECHATPAY.value());

        List<OrderItem> allOrderItem = new ArrayList<>();

        List<Order> orders = orderNumbers.stream().map(orderNumber -> {
            Order order = orderMapper.getOrderAndOrderItemByOrderNumber(orderNumber);
            allOrderItem.addAll(order.getOrderItems());
            return order;
        }).collect(Collectors.toList());
        //如果是积分订单增加积分购买日志,否则发送支付成功事件
        //更新用户积分和添加日志 如果是积分商品就更新购买积分商品记录及减少用户积分
        if(Objects.equals(orders.get(0).getOrderType(), OrderType.SCORE.value())){
            OrderSettlement orderSettlement = orderSettlements.get(0);
            Order order = orders.get(0);
            eventPublisher.publishEvent(new UpdateUserScoreEvent(ScoreLogType.SCORE_CASH.value(),orderSettlement.getPayScore(),0,
                    order.getOrderNumber(), "购买商品花费的积分",order.getUserId()));
        }else {
            eventPublisher.publishEvent(new PaySuccessOrderEvent(orders, allOrderItem, payNo));
        }
        return orders;
    }



}
